home *** CD-ROM | disk | FTP | other *** search
- Was ist M2POSIX ?
- =================
-
- Diese Modulsammlung soll einige der POSIX-Systemaufrufe (die bisher
- nur für ``C'' definiert sind) auch unter Modula-2 verfügbar machen.
- Insbesondere unter GEMDOS werden ja manche Dinge völlig
- unterschiedlich zu *IX-Systemen, und damit auch POSIX, gehandhabt. Ich
- denke da nur an das Suchen von Dateien: Unter GEMDOS werden dazu die
- Betriebssystemaufrufe "Fsfirst()" und "Fsnext()" benutzt, unter POSIX
- wird ein Verzeichnis mit "opendir()" geöffnet, jeweils der Name der
- nächsten im Verzeichnis enthaltenen Datei mit "readdir()" ermittelt,
- mit "fnmatch()" wird überprüft, ob der Name mit der oder den gesuchten
- übereinstimmt (dabei können die ``Wildcards'' *, ? und [...] benutzt
- werden) und schließlich werden mit "stat()" alle weiteren
- Informationen über die Datei eingeholt (unter GEMDOS stehen die
- vorhandenen Informationen in der DTA). Ein Beispiel für die Ermittlung
- von Dateien nach diesem Muster ist in LISTDIR.MPP enthalten, das ein
- sehr vereinfachtes ``ls'' darstellt. Außerdem können Pfadnamen nach
- *IX-Konvention angegeben werden (z.B. / statt \); diese werden, soweit
- möglich, in DOS-Äquivalente überführt. Für die Länge von Pfadnamen gibt
- es (bei den meisten Prozeduren) keine Begrenzung.
-
- Als Grundlage dieser Modulsammlung diente die ``C''-Bibliothek MiNTLib
- von Eric R. Smith, dem Autor von MiNT. Diese Bibliothek macht die
- speziellen Eigenschaften von MiNT, dem GEMDOS-Multitasking-Ersatz bzw.
- der MultiTOS-Grundlage, auch innerhalb der (*IX)-Standardbibliothek
- für ``C''-Compiler, speziell dem GNU-C-Compiler, zugänglich.
-
- Abgesehen vom reinen Übertragen ``C'' --> Modula sind einige
- Funktionen gleichgeblieben, aber bei den meisten habe ich erweitert,
- verkürzt, verändert, Fehler beseitigt, Fehler hinzugefügt oder sonst
- irgendwas. Ich habe auch versucht die Funktionen etwas mehr dem
- POSIX-Standard anzugleichen. Bei der Modulaufteilung und der
- Namensgebung war ich manchmal etwas ratlos, aber zumindest die
- Funktionsnamen sind, bis auf wenige Ausnahmen, gleichgeblieben. Wer
- einen Compiler hat, der Unterstriche in Bezeichnern erlaubt, und
- lieber die Originalnamen verwenden möchte, kann die Module mit dem
- Präprozessor und der Datei POSIX_ID.M2H bearbeiten, die die
- entsprechenden Namensumsetzungen enthält. Zeitweise war für die
- Moduleinteilung auch ein einzelnes Modul im Gespräch, z.B. 'SYS' oder
- 'POSIX', aber das wäre wohl ein ziemliches Monster an Umfang geworden;
- auch die Struktur der POSIX-C-Header zu übernehmen schien mir nicht so
- geeignet, da hier die Verteilung der Funktionen schlecht geregelt wäre
- (in 'UNISTD' stände dann fast alles und in den anderen Modulen, wie
- 'STAT', 'DIRENT' u.ä. jeweils nur ein paar wenige Funktionen).
- Zusammengehörende Funktionen sind zwar in den jeweiligen Modulen
- zusammengefaßt, es ist aber ein Modul POSIX1 vorhanden, in dem alle
- POSIX-Funktionen, -Typen und -Konstanten als Reexport bzw.
- Prozedurvariable deklariert sind, sodaß der Import aus einem einzigen
- Modul ausreicht, ohne daß ein Riesenmodul entsteht oder zusätzlicher
- Verwaltungsaufwand zur Laufzeit. Auf die gleiche Weise gibt es ein
- Modul ANSIC, in dem Funktionen reexportiert werden, die dem ANSI-C-
- Standard zuzuordnen sind und zumindest teilweise ebenfalls POSIX-1-
- Funktionen sind.
-
- Die Funktionen machen, soweit möglich, von MiNT Gebrauch, falls dieses
- geladen ist. Es sollte aber mindestens die Version 0.96 benutzt
- werden, da nur überprüft wird, ob MiNT vorhanden ist, und nicht,
- welche Version benutzt wird -- mit Version 0.95 oder kleiner laufen
- einige Funktionen nicht! Dies ist eine Änderung gegenüber den vorigen
- Versionen von M2POSIX, aber ich gehe davon aus, daß jemand, der MiNT
- einsetzt, entweder MultiTOS besitzt, oder sich selbst eine lauffähige
- Version von MiNT aus den frei verfügbaren Quelltexten erzeugen kann,
- oder jemanden kennt, der dies kann.
-
- Diese Module bestehen nicht aus reinem Modula-Quellcode, sondern
- enthalten noch Kommandos eines ``C''-Präprozessors, der die
- Übersetzbarkeit der Module unter verschiedenen Compilern erleichtern
- soll. Nähere Informationen zum Präprozessor geben die folgenden
- Abschnitte.
-
-
- Für wen ist M2POSIX geeignet ?
- ==============================
-
- Diese Modulsammlung ist nichts für Anfänger! Wer sich mit den Modulen
- befassen will, sollte schon mit einem Kommandointerpreter umgehen
- können, und wissen wie ein Präprozessor zu benutzen ist. Weiterhin
- sollte man bereit sein, sich auf ein bißchen Experimentieren
- einzulassen. Wer Änderungen vornehmen will, muß vor allem aufmerksam
- die Implementationsmodule und die Header-Dateien durchsehen. Also
- nochmal: DIESE MODULE SIND NUR ETWAS FÜR LEUTE, DIE BEREIT SIND, SICH
- MEHR ODER WENIGER INTENSIV DAMIT AUSEINANDERZUSETZEN!!!
-
- An zusätzlichen Programmen, neben einem M2-Compiler, werden benötigt:
-
- o Ein Kommandointerpreter, vorzugsweise GULÄM.PRG.
-
- o Ein ``C''-Präprozessor, vorzugsweise GCC-CPP.TTP bzw. CPP.TTP
- (Der GNU-C-Präprozessor wird im Verzeichnis 'cpp' mitgeliefert).
-
- Diese Programme findet man bestimmt auf jedem FTP-Server (z.B.
- ftp.uni-muenster.de, ftp.uni-paderborn.de, ftp.cs.tu-berlin.de). Der
- Präprozessor dürfte meistens zusammen mit dem GNU-C-Compiler in einem
- gemeinsamen Archiv zu finden sein. Außerdem gibt es beide Programme
- auch noch auf (teuren) PD-Disketten.
-
-
-
- Bedingungen, unter denen M2POSIX verwendet werden darf
- ======================================================
-
- Die Verwendung von M2POSIX unterliegt keiner Einschränkung, außer daß
- bei der Weitergabe alle Dateien unverändert enthalten sein müssen
- (abgesehen von einer Komprimierung). Natürlich dürfen für die
- Weitergabe auch keine Gebühren zusätzlich zu Diskettenkosten,
- Kopierkosten o.ä. verlangt werden!
-
- Ich übernehme keinerlei Verantwortung für die Korrektheit und
- Verwendbarkeit der Funktionen. Wer M2POSIX benutzt, ist selber für
- alle evtl. Folgen verantwortlich.
-
-
- Warum ein Präprozessor ?
- ========================
-
- Leider verstehen nicht alle Modula-Compiler einen gemeinsamen
- ``Dialekt''. Sicher -- die Sprache ist in einer Sprachbeschreibung
- definiert worden, aber zum einen gibt es mehrere Versionen dieser
- Beschreibung (PIM1..PIM4), zum anderen ist lediglich die Syntax formal
- definiert (BNF), die Semantik aber in Form natürlichsprachlicher
- Texte, sodaß einige Dinge nicht eindeutig festgelegt sind (werden
- können). Außerdem haben die Compiler-Hersteller auch eigene
- Restriktionen und/oder Erweiterungen hinzugefügt. Diese Situation wird
- sich erst ändern, wenn sich die Hersteller an die ISO-Norm für
- Modula-2 halten, hier wird nämlich auch die Semantik bis ins kleinste
- formal definiert.
-
- Die Unterschiede bestehen vor allem in folgenden Bereichen:
-
- o standardmäßige Größen von INTEGER und CARDINAL (16 oder 32 Bit)
-
-
- o Typtransfer: das Ändern des Typs eines Ausdrucks, ohne daß dafür
- Code generiert wird; d.h. das betreffende Bitmuster wird nur anders
- interpretiert, bzw. die Typprüfung des Compilers umdirigiert.
-
- o Typkonvertierung: das Ändern des Typs eines Ausdrucks, wobei evtl.
- Code generiert wird, z.B. bei der Wandlung zwischen SHORT- und
- LONG-Typen.
-
- o Adressarithmetik
-
-
- o Setzen und Lesen von Prozessorregistern.
-
- o Kennzeichnung von LONG-Konstanten
-
-
- Um diese Unterschiede möglichst aus dem Weg zu räumen, werden die
- Module mit Präprozessormakros versehen, die z.T. von der Syntax her
- wie ISO-M2-Code aussehen (z.B. CAST, VAL, ADDADR, SUBADR, DIFADR, INT
- usw.). In der Datei PORTAB.M2H, die die Definitionen enthält, werden
- die Makros dann auf die compilerspezifischen Konstruktionen
- abgebildet. Eine weitere Datei mit Makros ist OSCALLS.M2H; sie enthält
- die Definitionen für die Aufrufe der Betriebssystemfunktionen.
-
- Durch das Konzept der Makros können die Module also einheitlich für
- unterschiedliche Compiler programmiert werden; die Unterschiede werden
- dann erst beim Bearbeiten mit dem Präprozessor berücksichtigt, das am
- besten als erster Pass des Übersetzungsvorganges betrachtet wird. (Bei
- ``C''-Compilern ist dieses Vorgehen ja bereits integriert, es hindert
- einen aber niemand daran, dies auch für andere Sprachen, wie Modula-2,
- zu benutzen.)
-
- Um Module mit und ohne Makros leicht auseinanderhalten zu können,
- verwende ich folgende Extensionen für M2-Dateien mit
- Präprozessorkommandos:
-
- .DPP für Definitionsmodule,
- .IPP für Implementationsmodule und
- .MPP für Programmodule
-
- Diese Kennzeichnung ist natürlich nur ein Vorschlag.
-
-
- Die Benutzung eines ``C''-Präprozessors hat natürlich(?) auch
- Nachteile:
-
- o Die Modula-Kommentarklammern sind keine ``C''-Kommentarklammern --
- deshalb werden Zeichenketten, die mit definierten Makros
- übereinstimmen, auch innerhalb von Modula-Kommentaren durch den
- Präprozessor ersetzt. Als Behelf kann man die entsprechenden
- Schlüsselworte innerhalb der Modula-Kommentare in doppelte
- Anführungszeichen (") setzen, da der Präprozessor, zumindest der
- GNU-C-Präprozessor, keine Makros in C-Strings ersetzt.
-
- o Der Backslash '\' hat für den Präprozessor eine Spezialbedeutung; je
- nach dem (oder den) nachfolgenden Zeichen wird für die Kombination
- der Zeichen nachher durch den Compiler ein Spezial (meistens
- Control)-Zeichen eingesetzt. Obwohl nicht der Präprozessor für die
- Ersetzung verantwortlich ist, meldet er jedoch einen Fehler (->
- "unterminated string constant"), wenn hinter dem Backslash in einer
- Zeichen- oder Stringkonstante kein Zeichen mehr folgt. (Das gilt
- zumindest für den GNU-C-Präprozessor.)
-
-
-
- Präprozessieren der Module
- ==========================
-
- Im folgenden wird davon ausgegangen, daß ``Guläm'' als CLI zusammen
- mit den vorgefertigten Batch-Dateien benutzt, und als Präprozessor der
- GNU-C-Präprozessor verwendet wird. Wer einen anderen CLI (z.B. Mupfel)
- benutzt, oder gar einen anderen Präprozessor, muß entsprechende
- Änderungen vornehmen.
-
- Der Aufbau der Batch-Dateien ist als Kommentar in den Dateien selbst
- enthalten, es sollte also keine größeren Schwierigkeiten geben, diese
- an andere Gegebenheiten anzupassen.
-
- Beim Präprozessieren wird am besten folgende Reihenfolge eingehalten:
-
- 1) Erstellen einer Datei X<System>.G, die die Batch-Datei X_M2.G mit
- den nötigen Parametern aufruft, d.h. Name des Compilers,
- Zielverzeichnis, Endungen von Definitions- und
- Implementationsmodulen. Meine Datei für LPR-Modula sieht so aus:
-
- Name: XLPR.G
- Inhalt: x_m2 LPRM2 m: def mod
-
- Die präprozessierten Module landen bei mir auf der RAM-Disk M:\.
-
- Eine ähnliche Datei muß auch für das Präprozessieren der Testmodule
- erstellt werden, wobei hier nur die Endung für Programmodule
- benötigt wird:
-
- Name: TLPR.G
- Inhalt: t_m2 LPRM2 m: mod
-
- 2) In der Datei PORTAB.M2H werden gleich zu Anfang die Makros
-
- #if 0
- #define __RES_ON_STACK__
- #endif
-
- #if 1
- #define __LONG_WHOLE__
- #endif
-
- #if 1
- #define __LONG_REAL__
- #endif
-
- #if 1
- #define __REG_VARS__
- #endif
-
- definiert. Die Einstellung dieser Makros kann auf Wunsch verändert
- werden. Falls die Bedingung im umgebenden #if gleich 0 ist, ist das
- Makro undefiniert und damit ausgeschaltet, sonst ist es eingeschaltet.
- Falls die entsprechende Option bei einem Compiler nicht einstellbar
- ist, hat das Makro keine Bedeutung. Falls die Option nur beim Start
- des Compilers aber nicht im Quelltext einstellbar ist, MUß(!) dieses
- Makro mit der globalen Compilereinstellung übereinstimmen. Falls die
- Option dagegen im Quelltext gesetzt werden kann, wird sie automatisch,
- zusammen mit anderen Grundeinstellungen, abhängig von diesem Makro
- gesetzt.
- Die Bedeutung der Makros ist wie folgt:
-
- __RES_ON_STACK__:
- Die Ergebnisse von Funktionen werden auf dem Stack übergeben, sonst
- in Registern (D0/D1).
-
- __LONG_WHOLE__:
- Die Typen CARDINAL und INTEGER sind identisch mit LONGCARD und
- LONGINT, also den größten Ganzzahltypen, entsprechend ISO, sonst
- mit SHORTCARD und SHORTINT.
-
- __LONG_REAL__:
- Der Typ REAL ist identisch mit LONGREAL, sonst mit SHORTREAL.
-
- __REG_VARS__:
- Lokale Variablen, die mit dem Attribut __REG__ versehen sind, werden
- als Registervariablen deklariert, sonst nicht.
-
- 3) Eintragen des vollständigen Pfades der Datei PORTAB.M2H in die
- Batch-Datei M2PPX.G. PORTAB.M2H kann in einem beliebigen
- Verzeichnis stehen, da nur an dieser einen Stelle auf sie
- zugegriffen wird. Sinnvoll ist es jedoch, sie in dem Verzeichnis
- unterzubringen, wo auch die anderen Header-Dateien stehen, falls
- solche existieren (z.B. vom ``C''-Compiler).
-
- 4) Die Batch-Dateien (bei mir M2PPX.G, X_M2.G, XLPR.G, T_M2.G und
- TLPR.G), der Präprozessor CPP.TTP bzw. GCC-CPP.TTP und das kleine
- Programm X2D1.TOS werden in ein Verzeichnis kopiert, wo der
- Kommandointerpreter sie als ausführbare Dateien finden kann; das
- Verzeichnis muß also in der Environmentvariablen PATH erwähnt sein.
- Bei mir steht deshalb in GULAM.G folgende Definition (die ab-
- schließenden Punkte sollen weitere Pfade andeuten):
-
- set path '.,e:\usr\bin,e:\bin,...' ,
-
- wobei die Batch-Dateien und X2D1.TOS im ersten Verzeichnis stehen
- und der Präprozessor im zweiten. Bemerkung: Nach einem 'set path'
- wird bei Guläm automatisch die Environmentvariable PATH gesetzt.
-
- 5) Alle Dateien mit den Endungen .DPP, .IPP und .MPP und die Datei
- OSCALLS.M2H in ein Verzeichnis kopieren. OSCALLS.M2H kann
- alternativ ebenfalls in das Verzeichnis kopiert werden, wo die
- anderen Header-Dateien stehen, dann muß jedoch der Präprozessor
- wissen, wo er zu suchen hat; in meinem GULAM.G steht deswegen
- folgende Zeile:
-
- setenv GNUINC e:\usr\include\m2,e:\usr\include
-
- Im ersten Verzeichnis stehen dabei alle Modula-2-Header, im zweiten
- die ``C''-Header.
-
- 6) Guläm starten und in das Verzeichnis mit den M2-Dateien wechseln.
-
- 7) Einfach die in Punkt 1) erstellten Batch-Dateien aufrufen, z.B.
- mit:
-
- XLPR
-
- und wenn kein Fehler aufgetreten ist:
-
- TLPR
-
- Dann sollten im Zielverzeichnis die Module in reinem M2-Quellcode
- stehen. Die Module können dann mit dem Modula-Compiler übersetzt
- werden. Da die Module teilweise voneinander abhängig sind, muß beim
- Übersetzen natürlich eine bestimmte Reihenfolge eingehalten werden,
- hierfür kann aber einfach die gleiche Reihenfolge benutzt werden,
- wie sie in der Batch-Datei X_M2.G für das Präprozessieren verwendet
- wurde.
-
-
- Anpassung an andere Compiler
- ============================
-
- Gleich vorneweg: Folgende Compiler werden nicht berücksichtigt:
-
- o ana-systems m2 (ANAM2): ein Shareware-Compiler, der sich an PIM2
- orientiert; der Hauptnachteil ist aber, daß er keine arithmetischen
- 16-Bit-Typen kennt.
-
- o Modular Systems (MSM2): orientiert sich auch irgendwo zwischen PIM2
- und PIM3, hat aber viel zu viele Eigenheiten.
-
- o FTL-Modula: hat einige Compilerfehler, die einem das Leben schwer,
- wenn nicht gar unmöglich machen, zumindest in der Version 1.18.
-
- Ich behaupte nicht, daß diese Compiler schlecht wären, es ist mir aber
- zu viel Arbeit, auf die Eigenheiten dieser Systeme Rücksicht zu
- nehmen.
-
- Momentan werden nur die Compiler LPR (PD-Compiler der TU-München),
- Megamax, Hänisch und TDI (kommerzielle Compiler) unterstützt; da der
- SPC-Compiler (nur der Compiler, nicht etwa das ganze System) aber fast
- identisch zu LPR ist, dürfte auch dieser geeignet sein (Ähnliches
- dürfte auch für andere Compiler gelten, die vom Original-ETH-Compiler
- abstammen). Wer die Module an sein System anpassen will, muß auf jeden
- Fall die Header-Datei PORTAB.M2H anpassen, wahrscheinlich auch
- OSCALLS.M2H, da dort die Betriebssystemaufrufe definiert werden.
- Außerdem muß im Modul 'cmdline' die systemspezifische Prozedur zur
- Ermittlung der 'Basepage' verwendet werden, vielleicht ist die
- 'Basepage' auch als Variable in irgendeinem Systemmodul deklariert. Im
- Modul 'lib' sind einige Assemblerprozeduren; die Routinen selber sind
- allgemein gehalten, sodaß hier keine Anpassung nötig sein dürfte,
- evtl. müssen aber andere Register gerettet werden, dazu steht aber ein
- Kommentar im Quelltext.
-
- Es kann auch sein, daß im Quellcode spezielle Abfragen auf das System
- nötig werden, z.B in der Form:
-
- ...
- #if (defined <System>M2)
- ...
- #else
- ...
- #endif
- ...
-
- Es sollte jedoch versucht werden, sämtliche Compiler-Abhängigkeiten in
- die Header-Dateien zu verlegen -- soweit möglich.
-
- Am besten ist es, mal die Testmodule (mit der Endung .MPP) zu
- übersetzen, und sowohl unter GEMDOS als auch unter MiNT laufen zu
- lassen -- vorausgesetzt natürlich, daß der Compiler dazu überredet
- werden kann, die Module zu übersetzen. Falls der Compiler für INTEGER
- und CARDINAL per Option 16 oder 32 Bit benutzen kann, sollten auch
- beide Einstellungen ausprobiert werden.
-
- Beim HM-Compiler werden nur noch Versionen >= 5.1 unterstützt.
-
- Beim LPR-Compiler müssen alle Tests in der Shell ausgeschaltet
- werden, da es Assemblerprozeduren mit Rückgabewert gibt (Das Laufzeit-
- system beschwert sich sonst über ein fehlendes RETURN.)
-
- Die ``Test''-Module sind allerdings keine vollständigen Tests,
- vielmehr werden einfach nur einige der Funktionen mit
- unterschiedlichen Parametern aufgerufen, und geprüft, ob das Erwartete
- passiert. Z.T. ist auch die Überprüfung durch den Benutzer
- erforderlich, oder es werden einfach nur Systemeinstellungen
- abgefragt. Für weitere Informationen über die Anwendung der Testmodule
- sollte der Quellcode durchgesehen werden.
-
- Zu Demonstrationszwecken wurden einige der Testmodule auch übersetzt.
-
- Da bei solchen Anpassungen einiges schief gehen kann, sollte
- vielleicht eine RAM-Disk benutzt werden, auf der dann Dateien ohne
- Auswirkungen zerstört werden können... Auf jeden Fall übernehme ich
- keine Verantwortung für zerschossene Festplatten oder ähnliches...
-
- Eine Anpassung an MSDOS- oder gar *IX-Systeme benötigt sicherlich
- einiges an Arbeit, ich will aber niemanden davon abhalten...
-
- Generell: Ich würde mich freuen, wenn mir jemand, der eine Anpassung
- vorgenommen hat, eine Kopie zukommen läßt. Das gilt natürlich auch für
- Anregungen, Fehlermeldungen u. ä.
-
- Meine Adresse lautet:
-
- Holger Kleinschmidt
- Promenadenstr. 11 B
- 12207 Berlin
-
-
- Literatur
- =========
-
- Zlotnick, F.. The POSIX.1 Standard: A Programmer's Guide. The
- Benjamin/Cummings Publishing Company, 1991
-